/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkSampleGbDevice.h"
#include "MkEvent/MkTimer.h"
#include "MkUtil/MkUtil.h"
#include "MkGb28181/MkGbPtz.h"
#include "MkGb28181/MkGbUtil.h"
#include "MkUtil/MkTime.h"
#include "MkRtp/MkRtpServerPool.h"
#include "MkUtil/MkLog.h"
#include "MkSdp/MkSdp.h"
#include "MkUtil/MkMd5.h"

CMkSampleGbDevice::CMkSampleGbDevice(CMkEventPool* pEventPool, CMkTimer* pTimer)
    : CMkGb28181(pEventPool, pTimer)
    , m_bServerTcp(FALSE)
    , m_bAlarmSetGuard(FALSE)
    , m_bAlarming(TRUE)
    , m_bRecording(FALSE)
    , m_bOnline(FALSE)
    , m_bSubscribeCatalog(FALSE)
    , m_bSubscribePtzPosition(FALSE)
    , m_bSubscribeMobilePosition(FALSE)
    //, m_pRtpPool(nullptr)
{
    CMkUtil::Utf8ToGbk("测试设备", m_DeviceName);
    CMkSipUtil::GetInstance().SetMessageContentDebug(TRUE);

    m_ChannelItem.Address = "Address";
    m_ChannelItem.CivilCode = "3402020000";
    m_ChannelItem.DeviceID = "34020200001310000001";
    m_ChannelItem.Manufacturer = "Mk";
    m_ChannelItem.Model = "Ipc Camera";
    CMkUtil::Utf8ToGbk("测试通道", m_ChannelItem.Name);
    m_ChannelItem.Owner = "Owner";
    m_ChannelItem.ParentID = "34020200001320000001";
    m_ChannelItem.Parental = "0";
    m_ChannelItem.RegisterWay = "1";
    m_ChannelItem.SafetyWay = "0";
    m_ChannelItem.Secrecy = "0";
    m_ChannelItem.Status = "ON";

    m_AlarmItem.Address = "Address";
    m_AlarmItem.CivilCode = "3402020000";
    m_AlarmItem.DeviceID = "34020200001340000001";
    m_AlarmItem.Manufacturer = "Mk";
    m_AlarmItem.Model = "Alarm Out";
    CMkUtil::Utf8ToGbk("测试报警", m_AlarmItem.Name);
    m_AlarmItem.Owner = "Owner";
    m_AlarmItem.ParentID = "34020200001320000001";
    m_AlarmItem.Parental = "0";
    m_AlarmItem.RegisterWay = "1";
    m_AlarmItem.SafetyWay = "0";
    m_AlarmItem.Secrecy = "0";
    m_AlarmItem.Status = "ON";

    m_AudioOutItem.Address = "Address";
    m_AudioOutItem.CivilCode = "3402020000";
    m_AudioOutItem.DeviceID = "34020200001370000001";
    m_AudioOutItem.Manufacturer = "Mk";
    m_AudioOutItem.Model = "Audio Out";
    CMkUtil::Utf8ToGbk("测试语音通道", m_AudioOutItem.Name);
    m_AudioOutItem.Owner = "Owner";
    m_AudioOutItem.ParentID = "34020200001320000001";
    m_AudioOutItem.Parental = "0";
    m_AudioOutItem.RegisterWay = "1";
    m_AudioOutItem.SafetyWay = "0";
    m_AudioOutItem.Secrecy = "0";
    m_AudioOutItem.Status = "ON";

    m_SnapShot.MainParam["SnapNum"] = "1";
    m_SnapShot.MainParam["Interval"] = "2";
    m_SnapShot.MainParam["UploadUrl"] = "http://12.12.12.12/api/pic";
    m_SnapShot.MainParam["SessionID"] = "123";

    m_FrameMirrorType = 1;

    MkGbMessage SVCParamMsg;
    SVCParamMsg.MainParam["SVCSTMMode"] = "1";
    SVCParamMsg.MainParam["SVCSpaceSupportMode"] = "1";
    SVCParamMsg.MainParam["SVCTimeSupportMode"] = "1";
    MkGbMessage SurveillanceParamMsg;
    SurveillanceParamMsg.MainParam["TimeShowFlag"] = "1";
    SurveillanceParamMsg.MainParam["OSDShowFlag"] = "1";
    SurveillanceParamMsg.MainParam["AIShowFlag"] = "1";
    SurveillanceParamMsg.MainParam["GISShowFlag"] = "1";
    m_SVACDecodeConfig.MapMessage["SVCParam"] = SVCParamMsg;
    m_SVACDecodeConfig.MapMessage["SurveillanceParam"] = SurveillanceParamMsg;

    MkGbMessage ROIParamMsg;
    ROIParamMsg.MainParam["ROIFlag"] = "1";
    ROIParamMsg.MainParam["ROINumber"] = "1";
    ROIParamMsg.ItemName = "Item";
    MkGbMessage GbChild;
    GbChild.MainParam["ROISeq"] = "1";
    GbChild.MainParam["TopLeft"] = "1";
    GbChild.MainParam["BottomRight"] = "1";
    GbChild.MainParam["ROIQP"] = "1";
    ROIParamMsg.VecChildren.emplace_back(GbChild);
    m_SVACEncodeConfig.MapMessage["ROIParam"] = ROIParamMsg;

    MkGbMessage SVCParamMsg1;
    SVCParamMsg1.MainParam["SvCSpaceDomainMode"] = "1";
    SVCParamMsg1.MainParam["SVCTimeDomainMode"] = "1";
    SVCParamMsg1.MainParam["SSVCRatioValue"] = "1";
    SVCParamMsg1.MainParam["SVCSpaceSupportMode"] = "1";
    SVCParamMsg1.MainParam["SVCTimeSupportMode"] = "1";
    SVCParamMsg1.MainParam["SSVCRatioSupportList"] = "4:3/2:1";
    m_SVACEncodeConfig.MapMessage["SVCParam"] = SVCParamMsg1;

    MkGbMessage SurveillanceParamMsg1;
    SurveillanceParamMsg1.MainParam["TimeFlag"] = "1";
    SurveillanceParamMsg1.MainParam["OSDFlag"] = "1";
    SurveillanceParamMsg1.MainParam["AIFlag"] = "1";
    SurveillanceParamMsg1.MainParam["GISFlag"] = "1";
    m_SVACEncodeConfig.MapMessage["SVCParam"] = SurveillanceParamMsg1;

    MkGbMessage AudioParamMsg;
    AudioParamMsg.MainParam["AudioRecognitionFlag"] = "1";
    m_SVACEncodeConfig.MapMessage["AudioParam"] = AudioParamMsg;



    GbChild.MainParam.clear();
    GbChild.MainParam["StreamNumber"] = "0";
    GbChild.MainParam["VideoFormat"] = "2";
    GbChild.MainParam["Resolution"] = "2";
    GbChild.MainParam["FrameRate"] = "25";
    GbChild.MainParam["BitRateType"] = "1";
    GbChild.MainParam["VideoBitRate"] = "1";
    m_VideoParamAttribute.VecChildren.emplace_back(GbChild);
    GbChild.MainParam["StreamNumber"] = "1";
    m_VideoParamAttribute.VecChildren.emplace_back(GbChild);
    GbChild.MainParam["StreamNumber"] = "2";
    m_VideoParamAttribute.VecChildren.emplace_back(GbChild);
    m_VideoParamAttribute.ChildKey = "VideoParamAttribute";
    m_VideoParamAttribute.ItemName = "Item";

    m_VideoRecordPlan.MainParam["RecordEnable"] = "1";
    m_VideoRecordPlan.MainParam["RecordScheduleSumNum"] = "7";
    m_VideoRecordPlan.MainParam["StreamNumber"] = "1";
    MkGbMessage RecordScheduleMsg;
    RecordScheduleMsg.MainParam["WeekDayNum"] = "1";
    RecordScheduleMsg.MainParam["TimeSegmentSumNum"] = "2";
    RecordScheduleMsg.ChildKey = "TimeSegment";
    MkGbMessage TimeSegmentMsg;
    TimeSegmentMsg.MainParam["StartHour"] = "0";
    TimeSegmentMsg.MainParam["StartMin"] = "0";
    TimeSegmentMsg.MainParam["StartSec"] = "0";
    TimeSegmentMsg.MainParam["StopHour"] = "1";
    TimeSegmentMsg.MainParam["StopMin"] = "0";
    TimeSegmentMsg.MainParam["StopSec"] = "0";
    RecordScheduleMsg.VecChildren.emplace_back(TimeSegmentMsg);
    TimeSegmentMsg.MainParam["StartHour"] = "1";
    TimeSegmentMsg.MainParam["StartMin"] = "0";
    TimeSegmentMsg.MainParam["StartSec"] = "0";
    TimeSegmentMsg.MainParam["StopHour"] = "2";
    TimeSegmentMsg.MainParam["StopMin"] = "0";
    TimeSegmentMsg.MainParam["StopSec"] = "0";
    RecordScheduleMsg.VecChildren.emplace_back(TimeSegmentMsg);
    m_VideoRecordPlan.MapMessage["RecordSchedule"] = RecordScheduleMsg;

    m_VideoParamOpt.MainParam["DownloadSpeed"] = "0.25/1/2/4";
    m_VideoParamOpt.MainParam["Resolution"] = "1/2/3/4/5";

    m_AlarmReport.MainParam["MotionDetection"] = "1";
    m_AlarmReport.MainParam["FieldDetection"] = "1";

    m_PictureMask.MainParam["On"] = "1";
    m_PictureMask.MainParam["SumNum"] = "3";
    m_PictureMask.ChildKey = "RegionList";
    GbChild.MainParam.clear();
    GbChild.MainParam["Seq"] = "1";
    GbChild.MainParam["Point"] = "20,30,30,30";
    m_PictureMask.VecChildren.emplace_back(GbChild);
    GbChild.MainParam["Seq"] = "2";
    m_PictureMask.VecChildren.emplace_back(GbChild);
    GbChild.MainParam["Seq"] = "3";
    m_PictureMask.VecChildren.emplace_back(GbChild);

    m_VideoAlarmRecord.MainParam["RecordEnable"] = "1";
    m_VideoAlarmRecord.MainParam["RecordTime"] = "1";
    m_VideoAlarmRecord.MainParam["PreRecordTime"] = "5";
    m_VideoAlarmRecord.MainParam["StreamNumber"] = "1";

    m_OSDConfig.MainParam["Length"] = "1";
    m_OSDConfig.MainParam["Width"] = "1";
    m_OSDConfig.MainParam["TimeX"] = "1";
    m_OSDConfig.MainParam["TimeY"] = "1";
    m_OSDConfig.MainParam["TimeEnable"] = "1";
    m_OSDConfig.MainParam["TimeType"] = "1";
    m_OSDConfig.MainParam["TextEnable"] = "1";
    m_OSDConfig.MainParam["SumNum"] = "2";
    m_OSDConfig.ChildKey = "Item";
    GbChild.MainParam.clear();
    MkString StrGbk;
    CMkUtil::Utf8ToGbk("你好", StrGbk);
    GbChild.MainParam["Text"] = StrGbk;
    GbChild.MainParam["X"] = "0";
    GbChild.MainParam["Y"] = "1";
    m_OSDConfig.VecChildren.emplace_back(GbChild);
    CMkUtil::Utf8ToGbk("你好--你好", StrGbk);
    GbChild.MainParam["Text"] = StrGbk;
    GbChild.MainParam["X"] = "110";
    GbChild.MainParam["Y"] = "211";
    m_OSDConfig.VecChildren.emplace_back(GbChild);

    m_MapPreset["1"] = "1";
    m_MapPreset["2"] = "2";

    MkGbCruisePoint Point1;
    Point1.CruisePreindex = "1";
    Point1.CruiseSpeed = "15";
    Point1.CruiseStayTime = "5";

    MkCruiseTrack Track;
    Track.MapCruiseTrack[Point1.CruisePreindex] = Point1;
    Point1.CruisePreindex = "2";
    Track.MapCruiseTrack[Point1.CruisePreindex] = Point1;
    Track.CruiseId = "1";
    Track.CruiseName = "1";
    m_MapCruiseTrack[Track.CruiseId] = Track;
    Track.CruiseId = "2";
    Track.CruiseName = "2";
    m_MapCruiseTrack[Track.CruiseId] = Track;

    m_HomePositonParam["Enable"] = "1";
    m_HomePositonParam["PresetIndex"] = "1";
    m_HomePositonParam["ResetTime"] = "1";

    m_MobilePostionInterval = 3;
    GetTimer()->AddTimer([this]() {
        NotifyAlarm();
    }, 5000, m_TestAlarmTimer);

    GetTimer()->AddTimer([this]() {
        NotifyMobilePosition();
    }, m_MobilePostionInterval * 1000, m_MobilePostionTimer);

    GetTimer()->AddTimer([this]() {
        NotifyCatalog();
    }, 5000, m_CatalogTimer);

    GetTimer()->AddTimer([this]() {
        NotifyPtzPosition();
    }, 6000, m_PtzPositionTimer);
}

Uint32 CMkSampleGbDevice::StartDevice(const MkGbStartParam& Param)
{
    //m_pRtpPool = new CMkRtpPool(GetEventPool(), GetTimer());
    //if (!m_pRtpPool)
    //{
    //    return MallocFailed;
    //}
    //m_pRtpPool->SetTcpBeginPort(55000);
    //m_pRtpPool->SetUdpBeginPort(55000);
    //Uint32 ErrorCode = m_pRtpPool->Start();
    //MkCheckErrorLog(ErrorCode, "start rtp pool failed\n");

    return Start(Param, [this](const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb) {
        return OnGbRequest(pGbReq, Cb);
    });
}

Uint32 CMkSampleGbDevice::SetServerInfo(const MkString& GbId, const MkString& GbRealm, const MkString& GbHost, const Uint16& GbPort, const BOOL& bTcp)
{
    m_ServerId = GbId;
    m_ServerRealm = GbRealm;
    m_ServerHost = GbHost;
    m_ServerPort = GbPort;
    m_bServerTcp = bTcp;
    return AddRouter(GbId, GbRealm, GbHost, GbPort, bTcp);
}

Uint32 CMkSampleGbDevice::SetLocalInfo(const MkString& UserName, const MkString& Password, const Uint32& Expries, const Uint32 HeartBeatInterval, const Uint32& HeartBeatCount)
{
    m_DeviceUserName = UserName;
    m_DevicePassword = Password;
    m_DeviceExpries = Expries;
    m_HeartBeatInterval = HeartBeatInterval;
    m_HeartBeatCount = HeartBeatCount;
    CMkGbDeviceAuthorRequest Req;
    Req.m_RouterId = m_ServerId;
    Req.m_Expires = Expries;
    Req.m_DstId = m_ServerId;
    Req.m_Realm = m_ServerRealm;
    return RegisterToGbServer(Req);
}

Uint32 CMkSampleGbDevice::RegisterToGbServer(const CMkGbDeviceAuthorRequest& Req)
{
    return RegisterRequest(Req, [this,Req](Uint32 ErrorCode, const CMkGbResponse* pResponse) {
        const CMkGbDeviceAuthorResponse *pRes = dynamic_cast<const CMkGbDeviceAuthorResponse*>(pResponse);
        if (MkSipStatusUnauthorized + SipResponseErrorBegin == ErrorCode && pRes) {
            MkString Realm = pRes->m_Realm.substr(1, pRes->m_Realm.size() - 2);
            MkString Nonce = pRes->m_Nonce.substr(1, pRes->m_Nonce.size() - 2);
            if ("MD5"==pRes->m_Algorithm)
            {
                MkString Ha1 = CMkMd5Encode::Encode(m_DeviceUserName + ":" + Realm + ":" + m_DevicePassword);
                MkString Ha2 = CMkMd5Encode::Encode("REGISTER:" + pRes->m_Uri);
                MkString Ha3 = CMkMd5Encode::Encode(Ha1 + ":" + Nonce + ":" + Ha2);
                CMkGbDeviceAuthorRequest ReReq;
                ReReq.m_UserName = m_DeviceUserName;
                ReReq.m_Algorithm = pRes->m_Algorithm;
                ReReq.m_Expires = m_DeviceExpries;
                ReReq.m_Realm = Realm;
                ReReq.m_Nonce = Nonce;
                ReReq.m_RouterId = m_ServerId;
                ReReq.m_DstId = m_ServerId;
                ReReq.m_Response = Ha3;
                ReReq.m_Uri = pRes->m_Uri;
                ReReq.m_RegisterId = pRes->m_RegisterId;
                //TODO Add
                RegisterToGbServer(ReReq);
            }

        } else if (NoneError == ErrorCode) {
            m_bOnline = TRUE;
            NotifyKeepAlive();
            GetTimer()->AddTimer([this]() {
                NotifyKeepAlive();
            }, m_HeartBeatInterval * 1000, m_KeepAliveTimer);
        } else {
            MkString RegisterDelayer;
            GetTimer()->AddDelayer([this,Req]() {
                CMkGbDeviceAuthorRequest ReReq;
                ReReq.m_RouterId = m_ServerId;
                ReReq.m_Expires = Req.m_Expires;
                ReReq.m_DstId = m_ServerId;
                ReReq.m_Realm = m_ServerRealm;
                RegisterToGbServer(ReReq);
            }, 5 * 1000, RegisterDelayer);
        }
    });
}

Uint32 CMkSampleGbDevice::NotifyKeepAlive()
{
    CMkGbMessageRequest Req;
    Req.m_RouterId = m_ServerId;
    Req.m_DstId = m_ServerId;
    Req.m_DeviceId = GetSipId();
    Req.m_CmdType = "Keepalive";
    Req.m_MessageType = "Notify";
    return MessageRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {
        if (NoneError == ErrorCode) {
            m_LastKeepAliveTime = NowMkTime;
        } else if (NowMkTime - m_LastKeepAliveTime > (Uint64)m_HeartBeatInterval*m_HeartBeatCount * 1000 * 1000) {
            m_bOnline = FALSE;
            GetTimer()->DeleteDelayer(m_KeepAliveTimer);
            MkString RegisterDelayer;
            GetTimer()->AddDelayer([this]() {
                RegisterToGbServer(CMkGbDeviceAuthorRequest());
            }, 5 * 1000, RegisterDelayer);
        }
    });
}

Uint32 CMkSampleGbDevice::OnGbRequest(const CMkGbRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!m_bOnline) {
        Cb(SystemError, nullptr);
        return NoneError;
    }
    Uint32 ErrorCode = NoneError;
    switch (pGbReq->m_RequestType) {
    case MkGbRequestMessage:
        ErrorCode = OnGbMessageRequest(dynamic_cast<const CMkGbMessageRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestSubscribe:
        ErrorCode = OnGbSubscribeRequest(dynamic_cast<const CMkGbSubscribeRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestNotify:
        ErrorCode = OnNotifyRequest(dynamic_cast<const CMkGbNotifyRequest*>(pGbReq), Cb);
        break;
    case MkGbRequestInvite:
        ErrorCode = OnGbInviteRequest(dynamic_cast<const CMkGbInviteReqeust*>(pGbReq), Cb);
        break;
    default:
        break;
    }
    return ErrorCode;
}

Uint32 CMkSampleGbDevice::OnGbMessageRequest(const CMkGbMessageRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    Uint32 ErrorCode = InvalidParams;
    CMkGbMessageResponse Response;
    CMkGbMessageResponse* pRes = nullptr;
    if ("Query" == pGbReq->m_MessageType) {
        if ("DeviceStatus" == pGbReq->m_CmdType
            && (pGbReq->m_DeviceId == GetSipId() || pGbReq->m_DeviceId == m_ChannelItem.DeviceID)) {
            ErrorCode = PacketDeviceStatus(pGbReq->m_Message, Response.m_Message);
        } else if ("Catalog" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == GetSipId()) {
            Response.m_SumNum = 3;
            ErrorCode = PacketCatalog(pGbReq->m_Message, Response.m_Message);
        } else if ("DeviceInfo" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == GetSipId()) {
            ErrorCode = PacketDeviceInfo(pGbReq->m_Message, Response.m_Message);
        } else if ("RecordInfo" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == m_ChannelItem.DeviceID) {
            Response.m_SumNum = 2;
            ErrorCode = PacketRecordInfo(pGbReq->m_Message, Response.m_Message);
        } else if ("ConfigDownload" == pGbReq->m_CmdType
            && (pGbReq->m_DeviceId == GetSipId()|| pGbReq->m_DeviceId == m_ChannelItem.DeviceID)) {
            ErrorCode = PacketConfigDownload(pGbReq->m_Message, Response.m_Message);
        } else if ("PresetQuery" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == m_ChannelItem.DeviceID) {
            Response.m_SumNum = m_MapPreset.size();
            ErrorCode = PacketPresetQuery(pGbReq->m_Message, Response.m_Message);
        } else if ("HomePositionQuery" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == m_ChannelItem.DeviceID) {
            ErrorCode = PacketHomePositionQuery(pGbReq->m_Message, Response.m_Message);
        } else if ("CruiseTrackListQuery" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == m_ChannelItem.DeviceID) {
            Response.m_SumNum = m_MapCruiseTrack.size();
            ErrorCode = PacketCruiseTrackListQuery(pGbReq->m_Message, Response.m_Message);
        } else if ("CruiseTrackQuery" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == m_ChannelItem.DeviceID) {
            MkMapString::const_iterator it = pGbReq->m_Message.MainParam.find("Number");
            if (it != pGbReq->m_Message.MainParam.end()) {
                MkMap<MkString, MkCruiseTrack>::iterator itCruise = m_MapCruiseTrack.find(it->second);
                if (itCruise != m_MapCruiseTrack.end()) {
                    Response.m_SumNum = itCruise->second.MapCruiseTrack.size();
                    ErrorCode = PacketCruiseTrackQuery(pGbReq->m_Message, Response.m_Message);
                }
            } else {
                ErrorCode = InvalidParams;
            }
        } else if ("PTZPosition" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == m_ChannelItem.DeviceID) {
            ErrorCode = PacketPTZPosition(pGbReq->m_Message, Response.m_Message);
        } else if ("SDCardStatus" == pGbReq->m_CmdType
            && pGbReq->m_DeviceId == GetSipId()) {
            Response.m_SumNum = 2;
            ErrorCode = PacketSDCardStatus(pGbReq->m_Message, Response.m_Message);
        }
        pRes = &Response;
    } else if ("Control" == pGbReq->m_MessageType) {
        if ("DeviceConfig" == pGbReq->m_CmdType) {
            ErrorCode = PacketDeviceConfig(pGbReq->m_DeviceId, pGbReq->m_Message, Response.m_Message);
            pRes = &Response;
        } else if ("DeviceControl" == pGbReq->m_CmdType) {
            ErrorCode = PacketDeviceControl(pGbReq->m_DeviceId, pGbReq->m_Message, &pRes, Response);
        }
    } else if ("Notify" == pGbReq->m_MessageType) {
        if ("Broadcast" == pGbReq->m_CmdType) {
            MkMapString::const_iterator itSourceId = pGbReq->m_Message.MainParam.find("SourceID");
            MkMapString::const_iterator itTargetId = pGbReq->m_Message.MainParam.find("TargetID");
            if (itTargetId == pGbReq->m_Message.MainParam.end()
                || itSourceId == pGbReq->m_Message.MainParam.end()
                || itTargetId->second != m_AudioOutItem.DeviceID) {
                ErrorCode = InvalidParams;
            } else {
                MkString Delayer;
                GetTimer()->AddDelayer([this, itSourceId]() {
                    StartGetAudio(itSourceId->second);
                }, 10, Delayer);
            }
            Response.m_Message.MainParam["Result"] = NoneError == ErrorCode ? "OK" : "ERROR";
            pRes = &Response;
        }
    }
    if (NoneError == ErrorCode) {
        Cb(ErrorCode, pRes);
    }
    return ErrorCode;
}

Uint32 CMkSampleGbDevice::OnGbSubscribeRequest(const CMkGbSubscribeRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    if ("MobilePosition" == pGbReq->m_CmdType) {
        MkMapString::const_iterator it = pGbReq->m_Message.MainParam.find("Interval");
        if (it != pGbReq->m_Message.MainParam.end()) {
            m_MobilePostionInterval = std::stoi(it->second);
            if (m_MobilePostionInterval) {
                GetTimer()->ChangeTimerInterval(m_MobilePostionTimer, m_MobilePostionInterval * 1000);
            }
        }
        m_bSubscribeMobilePosition = 0 != pGbReq->m_Expires;
        m_SubscribeMobilePositionId = pGbReq->m_SubscribeId;
        m_SubscribeMobilePositionEvent = pGbReq->m_Event;
        m_SubscribeMobilePositionExpires = pGbReq->m_Expires;
    } else if ("Catalog" == pGbReq->m_CmdType) {
        m_bSubscribeCatalog = 0 != pGbReq->m_Expires;
        m_SubscribeCatalogId = pGbReq->m_SubscribeId;
        m_SubscribeCatalogExpires = pGbReq->m_Expires;
        m_SubscribeCatalogEvent = pGbReq->m_Event;
    } else if ("PTZPosition" == pGbReq->m_CmdType)
    {
        m_bSubscribePtzPosition = 0 != pGbReq->m_Expires;
        m_SubscribePtzPositionId = pGbReq->m_SubscribeId;
        m_SubscribePtzPositionExpires = pGbReq->m_Expires;
        m_SubscribePtzPositionEvent = pGbReq->m_Event;
    }
    CMkGbSubscribeResponse Res;
    Res.m_SubscribeId = pGbReq->m_SubscribeId;
    Res.m_Message.MainParam["Result"] = "OK";
    Cb(NoneError, &Res);
    return NoneError;
}

Uint32 CMkSampleGbDevice::OnNotifyRequest(const CMkGbNotifyRequest* pGbReq, const MkGbResponseCallback& Cb)
{
    return NoneError;
}

Uint32 CMkSampleGbDevice::OnGbInviteRequest(const CMkGbInviteReqeust* pGbReq, const MkGbResponseCallback& Cb)
{
    if (!pGbReq) {
        return InvalidParams;
    }
    CMkSdp Sdp;
    Sdp.ParseContent(pGbReq->m_OfferSdp);
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketDeviceStatus(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    GbMessage.MainParam["DeviceTime"] = "2023-10-24T09:17:49";
    GbMessage.MainParam["Encode"] = "ON";
    GbMessage.MainParam["Online"] = "ONLINE";
    GbMessage.MainParam["Record"] = "OFF";
    GbMessage.MainParam["Result"] = "OK";
    GbMessage.MainParam["Status"] = "OK";
    GbMessage.ChildKey = "Alarmstatus";
    MkGbMessage GbChild;
    GbChild.MainParam["DeviceID"] = "34020000001340000001";
    GbChild.MainParam["DutyStatus"] = "ONDUTY";
    GbMessage.VecChildren.emplace_back(GbChild);
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketCatalog(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    GbMessage.ChildKey = "DeviceList";
    GbMessage.ItemName = "Item";
    MkGbMessage GbChild;
    GbChild.MainParam["Address"] = m_ChannelItem.Address;
    GbChild.MainParam["CivilCode"] = m_ChannelItem.CivilCode;
    GbChild.MainParam["DeviceID"] = m_ChannelItem.DeviceID;
    GbChild.MainParam["Manufacturer"] = m_ChannelItem.Manufacturer;
    GbChild.MainParam["Model"] = m_ChannelItem.Model;
    GbChild.MainParam["Name"] = m_ChannelItem.Name;
    GbChild.MainParam["Owner"] = m_ChannelItem.Owner;
    GbChild.MainParam["ParentID"] = m_ChannelItem.ParentID;
    GbChild.MainParam["Parental"] = m_ChannelItem.Parental;
    GbChild.MainParam["RegisterWay"] = m_ChannelItem.RegisterWay;
    GbChild.MainParam["SafetyWay"] = m_ChannelItem.SafetyWay;
    GbChild.MainParam["Secrecy"] = m_ChannelItem.Secrecy;
    GbChild.MainParam["Status"] = m_ChannelItem.Status;
    GbMessage.VecChildren.emplace_back(GbChild);
    GbChild.MainParam.clear();

    GbChild.MainParam["Address"] = m_AlarmItem.Address;
    GbChild.MainParam["CivilCode"] = m_AlarmItem.CivilCode;
    GbChild.MainParam["DeviceID"] = m_AlarmItem.DeviceID;
    GbChild.MainParam["Manufacturer"] = m_AlarmItem.Manufacturer;
    GbChild.MainParam["Model"] = m_AlarmItem.Model;
    GbChild.MainParam["Name"] = m_AlarmItem.Name;
    GbChild.MainParam["Owner"] = m_AlarmItem.Owner;
    GbChild.MainParam["ParentID"] = m_AlarmItem.ParentID;
    GbChild.MainParam["Parental"] = m_AlarmItem.Parental;
    GbChild.MainParam["RegisterWay"] = m_AlarmItem.RegisterWay;
    GbChild.MainParam["SafetyWay"] = m_AlarmItem.SafetyWay;
    GbChild.MainParam["Secrecy"] = m_AlarmItem.Secrecy;
    GbChild.MainParam["Status"] = m_AlarmItem.Status;
    GbMessage.VecChildren.emplace_back(GbChild);
    GbChild.MainParam.clear();

    GbChild.MainParam["Address"] = m_AudioOutItem.Address;
    GbChild.MainParam["CivilCode"] = m_AudioOutItem.CivilCode;
    GbChild.MainParam["DeviceID"] = m_AudioOutItem.DeviceID;
    GbChild.MainParam["Manufacturer"] = m_AudioOutItem.Manufacturer;
    GbChild.MainParam["Model"] = m_AudioOutItem.Model;
    GbChild.MainParam["Name"] = m_AudioOutItem.Name;
    GbChild.MainParam["Owner"] = m_AudioOutItem.Owner;
    GbChild.MainParam["ParentID"] = m_AudioOutItem.ParentID;
    GbChild.MainParam["Parental"] = m_AudioOutItem.Parental;
    GbChild.MainParam["RegisterWay"] = m_AudioOutItem.RegisterWay;
    GbChild.MainParam["SafetyWay"] = m_AudioOutItem.SafetyWay;
    GbChild.MainParam["Secrecy"] = m_AudioOutItem.Secrecy;
    GbChild.MainParam["Status"] = m_AudioOutItem.Status;
    GbMessage.VecChildren.emplace_back(GbChild);
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketDeviceInfo(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    GbMessage.MainParam["Channel"] = "1";
    GbMessage.MainParam["DeviceName"] = m_DeviceName;
    GbMessage.MainParam["Firmware"] = "V1.0.0.0";
    GbMessage.MainParam["Manufacturer"] = "Mk";
    GbMessage.MainParam["Model"] = "1.1";
    GbMessage.MainParam["Result"] = "OK";
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketRecordInfo(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    GbMessage.MainParam["Name"] = m_ChannelItem.Name;
    GbMessage.ItemName = "Item";
    MkGbMessage GbChild;
    GbChild.MainParam["StartTime"] = "2023-10-24T09:17:49";
    GbChild.MainParam["EndTime"] = "2023-10-24T09:17:49";
    GbMessage.VecChildren.emplace_back(GbChild);
    GbMessage.VecChildren.emplace_back(GbChild);
    GbMessage.ChildKey = "RecordList";
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketConfigDownload(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    MkMapString::const_iterator it = ReqMessage.MainParam.find("ConfigType");
    if (it == ReqMessage.MainParam.end()) {
        return InvalidParams;
    }
    MkVectorString VecString;
    CMkUtil::StringSplit(it->second, "/", VecString);
    MkVectorString::iterator itVec = VecString.begin();
    for (; itVec != VecString.end(); itVec++) {
        if ("SVACEncodeConfig" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_SVACEncodeConfig;
        } else if ("BasicParam" == *itVec) {
            m_BasicParam.MainParam["Name"] = m_DeviceName;
            m_BasicParam.MainParam["Expiration"] = std::to_string(m_DeviceExpries);
            m_BasicParam.MainParam["HeartBeatInterval"] = std::to_string(m_HeartBeatInterval);
            m_BasicParam.MainParam["HeartBeatCount"] = std::to_string(m_HeartBeatCount);
            GbMessage.MapMessage[*itVec] = m_BasicParam;
        } else if ("SVACDecodeConfig" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_SVACDecodeConfig;
        } else if ("VideoParamOpt" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_VideoParamOpt;
        } else if ("VideoParamAttribute" == *itVec) {
            GbMessage = m_VideoParamAttribute;
        } else if ("VideoRecordPlan" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_VideoRecordPlan;
        } else if ("VideoAlarmRecord" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_VideoAlarmRecord;
        } else if ("PictureMask" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_PictureMask;
        } else if ("FrameMirror" == *itVec) {
            GbMessage.MainParam["FrameMirror"] = std::to_string(m_FrameMirrorType);
        } else if ("AlarmReport" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_AlarmReport;
        } else if ("OSDConfig" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_OSDConfig;
        } else if ("SnapShot" == *itVec) {
            GbMessage.MapMessage[*itVec] = m_SnapShot;
        }
    }
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketPresetQuery(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    GbMessage.ItemName = "Item";
    GbMessage.ChildKey = "PresetList";
    MkMapString::iterator it = m_MapPreset.begin();
    for (; it != m_MapPreset.end(); it++) {
        MkGbMessage Child;
        Child.MainParam["PresetID"] = it->first;
        Child.MainParam["PresetName"] = it->second;
        GbMessage.VecChildren.emplace_back(Child);
    }
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketHomePositionQuery(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    MkGbMessage Child;
    Child.MainParam = m_HomePositonParam;
    GbMessage.MapMessage["HomePosition"] = Child;
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketCruiseTrackListQuery(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    GbMessage.ChildKey = "CruiseTrackList";
    GbMessage.ItemName = "CruiseTrack";
    MkMap<MkString, MkCruiseTrack>::iterator it = m_MapCruiseTrack.begin();
    for (; it != m_MapCruiseTrack.end(); it++) {
        MkGbMessage Child;
        Child.MainParam["Number"] = it->first;
        Child.MainParam["Name"] = it->second.CruiseName;
        GbMessage.VecChildren.emplace_back(Child);
    }
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketCruiseTrackQuery(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    MkMapString::const_iterator it = ReqMessage.MainParam.find("Number");
    if (it == ReqMessage.MainParam.end()) {
        return InvalidParams;
    }
    MkMap<MkString, MkCruiseTrack>::iterator itCruise = m_MapCruiseTrack.find(it->second);
    if (itCruise != m_MapCruiseTrack.end()) {
        GbMessage.MainParam["Number"] = itCruise->second.CruiseId;
        GbMessage.MainParam["Name"] = itCruise->second.CruiseName;
        GbMessage.ChildKey = "CruisePointList";
        GbMessage.ItemName = "CruisePoint";
        MkMap<MkString, MkGbCruisePoint>::iterator itPoint = itCruise->second.MapCruiseTrack.begin();
        for (; itPoint != itCruise->second.MapCruiseTrack.end(); itPoint++) {
            MkGbMessage Child;
            Child.MainParam["PresetIndex"] = itPoint->second.CruisePreindex;
            Child.MainParam["StayTime"] = itPoint->second.CruiseStayTime;
            Child.MainParam["Speed"] = itPoint->second.CruiseSpeed;
            GbMessage.VecChildren.emplace_back(Child);
        }
    }
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketPTZPosition(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    GbMessage.MainParam["Pan"] = "1.0";
    GbMessage.MainParam["Tilt"] = "1.0";
    GbMessage.MainParam["Zoom"] = "1.0";
    GbMessage.MainParam["HorizontalFieldAngle"] = "1.0";
    GbMessage.MainParam["VerticalFieldAngle"] = "1.0";
    GbMessage.MainParam["MaxViewDistance"] = "10.0";
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketSDCardStatus(const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    GbMessage.ChildKey = "SDCardStatusInfo";
    GbMessage.ItemName = "Item";
    MkGbMessage Child;
    Child.MainParam["ID"] = "2";
    Child.MainParam["HddName"] = "Name";
    Child.MainParam["Status"] = "ok";
    Child.MainParam["FormatProgress"] = "100";
    Child.MainParam["Capacity"] = "1";
    Child.MainParam["FreeSpace"] = "0";
    GbMessage.VecChildren.emplace_back(Child);
    Child.MainParam["ID"] = "1";
    Child.MainParam["HddName"] = "Name";
    Child.MainParam["Status"] = "ok";
    Child.MainParam["FormatProgress"] = "100";
    Child.MainParam["Capacity"] = "1";
    Child.MainParam["FreeSpace"] = "0";
    GbMessage.VecChildren.emplace_back(Child);
    return NoneError;
}

Uint32 CMkSampleGbDevice::PacketDeviceConfig(const MkString& DeviceId, const MkGbMessage& ReqMessage, MkGbMessage& GbMessage)
{
    Uint32 ErrorCode = NoneError;
    MkMapString::const_iterator it;
    if (ReqMessage.MapMessage.empty() && DeviceId == m_ChannelItem.DeviceID) {
        it = ReqMessage.MainParam.find("FrameMirror");
        if ("VideoParamAttribute" == ReqMessage.ChildKey) {
            m_VideoParamAttribute = ReqMessage;
        } else if (it != ReqMessage.MainParam.end()) {
            m_FrameMirrorType = std::stoi(it->second);
        } else {
            ErrorCode = InvalidParams;
        }
    } else {
        MkString ConfigType = ReqMessage.MapMessage.begin()->first;
        if ("BasicParam" == ConfigType && DeviceId == GetSipId()) {
            it = ReqMessage.MapMessage.begin()->second.MainParam.find("Name");
            if (it != ReqMessage.MapMessage.begin()->second.MainParam.end()) {
                m_DeviceName = it->second;
            }
            it = ReqMessage.MapMessage.begin()->second.MainParam.find("Expiration");
            if (it != ReqMessage.MapMessage.begin()->second.MainParam.end()) {
                m_DeviceExpries = std::stoi(it->second);
            }
            it = ReqMessage.MapMessage.begin()->second.MainParam.find("HeartBeatInterval");
            if (it != ReqMessage.MapMessage.begin()->second.MainParam.end()) {
                m_HeartBeatInterval = std::stoi(it->second);
                GetTimer()->ChangeTimerInterval(m_KeepAliveTimer, m_HeartBeatInterval * 1000);
            }
            it = ReqMessage.MapMessage.begin()->second.MainParam.find("HeartBeatCount");
            if (it != ReqMessage.MapMessage.begin()->second.MainParam.end()) {
                m_HeartBeatCount = std::stoi(it->second);
            }
        } else if ("SVACEncodeConfig" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_SVACEncodeConfig = ReqMessage.MapMessage.begin()->second;
        } else if ("SVACDecodeConfig" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_SVACDecodeConfig = ReqMessage.MapMessage.begin()->second;
        } else if ("VideoParamOpt" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_VideoParamOpt = ReqMessage.MapMessage.begin()->second;
        } else if ("VideoRecordPlan" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_VideoRecordPlan = ReqMessage.MapMessage.begin()->second;
        } else if ("VideoAlarmRecord" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_VideoAlarmRecord = ReqMessage.MapMessage.begin()->second;
        } else if ("PictureMask" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_PictureMask = ReqMessage.MapMessage.begin()->second;
        } else if ("AlarmReport" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_AlarmReport = ReqMessage.MapMessage.begin()->second;
        } else if ("OSDConfig" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_OSDConfig = ReqMessage.MapMessage.begin()->second;
        } else if ("SnapShotConfig" == ConfigType && DeviceId == m_ChannelItem.DeviceID) {
            m_SnapShot = ReqMessage.MapMessage.begin()->second;
            MkString SnapShotDelayer;
            GetTimer()->AddDelayer([this]() {
                NotifyUploadSnapShotFinished();
            }, 5000, SnapShotDelayer);
        } else {
            ErrorCode = InvalidParams;
        }
    }
    if (InvalidParams != ErrorCode) {
        GbMessage.MainParam["Result"] = NoneError == ErrorCode ? "OK" : "ERROR";
    }

    return ErrorCode;
}

Uint32 CMkSampleGbDevice::PacketDeviceControl(const MkString& DeviceId, const MkGbMessage& ReqMessage, CMkGbMessageResponse** ppRes, CMkGbMessageResponse& Res)
{
    MkString strValue;
    Uint32 ErrorCode = NoneError;
    if (NoneError == HasControlType(ReqMessage, "PTZCmd", strValue) && DeviceId == m_ChannelItem.DeviceID) {
        Uint32 ErrorCode = NoneError;
        CGbPtzCommand *pCmd = CGbPtzCommand::FromString(strValue);
        if (!pCmd) {
            return InvalidParams;
        }
        if (MkGbPtzSetPreset == pCmd->GetCmdType()) {
            MkString PresetName = std::to_string(pCmd->GetParam2());
            MkMap<MkString, struct _gb_message>::const_iterator it = ReqMessage.MapMessage.find("PtzCmdParams");
            if (it != ReqMessage.MapMessage.end()) {
                MkMapString::const_iterator itStr = it->second.MainParam.find("PresetName");
                if (itStr != it->second.MainParam.end()) {
                    PresetName = itStr->second;
                }
            }
            m_MapPreset[std::to_string(pCmd->GetParam2())] = PresetName;
        } else if (MkGbPtzClearPreset == pCmd->GetCmdType()) {
            MkMapString::iterator itPreset = m_MapPreset.find(std::to_string(pCmd->GetParam2()));
            if (itPreset != m_MapPreset.end()) {
                m_MapPreset.erase(itPreset);
            }
        } else if (MkGbPtzAddCruise == pCmd->GetCmdType()) {
            MkCruiseTrack Track;
            MkGbCruisePoint Point;
            Track.CruiseId = std::to_string(pCmd->GetParam1());
            Point.CruisePreindex = std::to_string(pCmd->GetParam2());
            Track.CruiseName = Track.CruiseId;
            MkMap<MkString, struct _gb_message>::const_iterator it = ReqMessage.MapMessage.find("PtzCmdParams");
            if (it != ReqMessage.MapMessage.end()) {
                MkMapString::const_iterator itStr = it->second.MainParam.find("CruiseTrackName");
                if (itStr != it->second.MainParam.end()) {
                    Track.CruiseName = itStr->second;
                }
            }
            MkMap<MkString, MkCruiseTrack>::iterator itTrack = m_MapCruiseTrack.find(Track.CruiseId);
            if (itTrack == m_MapCruiseTrack.end()) {
                Track.MapCruiseTrack[Point.CruisePreindex] = Point;
                m_MapCruiseTrack[Track.CruiseId] = Track;
            } else {
                itTrack->second.MapCruiseTrack[Point.CruisePreindex] = Point;
            }
        } else if (MkGbPtzDelCruise == pCmd->GetCmdType()) {
            MkMap<MkString, MkCruiseTrack>::iterator it = m_MapCruiseTrack.find(std::to_string(pCmd->GetParam1()));
            if (it != m_MapCruiseTrack.end()) {
                if (0x00 == pCmd->GetParam2()) {
                    it->second.MapCruiseTrack.clear();
                } else {
                    MkMap<MkString, MkGbCruisePoint>::iterator itPoint = it->second.MapCruiseTrack.find(std::to_string(pCmd->GetParam2()));
                    if (itPoint != it->second.MapCruiseTrack.end()) {
                        it->second.MapCruiseTrack.clear();
                    }
                }
            }
        } else if (MkGbPtzCruiseSpeed == pCmd->GetCmdType()) {
            MkMap<MkString, MkCruiseTrack>::iterator it = m_MapCruiseTrack.find(std::to_string(pCmd->GetParam1()));
            if (it != m_MapCruiseTrack.end()) {
                MkMap<MkString, MkGbCruisePoint>::iterator itPoint = it->second.MapCruiseTrack.find(std::to_string(pCmd->GetParam2()));
                if (itPoint != it->second.MapCruiseTrack.end()) {
                    itPoint->second.CruiseSpeed = std::to_string(pCmd->GetParam3());
                }
            }
        } else if (MkGbPtzCruiseStayTime == pCmd->GetCmdType()) {
            MkMap<MkString, MkCruiseTrack>::iterator it = m_MapCruiseTrack.find(std::to_string(pCmd->GetParam1()));
            if (it != m_MapCruiseTrack.end()) {
                MkMap<MkString, MkGbCruisePoint>::iterator itPoint = it->second.MapCruiseTrack.find(std::to_string(pCmd->GetParam2()));
                if (itPoint != it->second.MapCruiseTrack.end()) {
                    itPoint->second.CruiseStayTime = std::to_string(pCmd->GetParam3());
                }
            }
        }
    } else if (NoneError == HasControlType(ReqMessage, "IFrameCmd", strValue) && DeviceId == m_ChannelItem.DeviceID) {
        if ("Send" != strValue) {
            return InvalidParams;
        }
    } else if (NoneError == HasControlType(ReqMessage, "TeleBoot", strValue) && DeviceId == GetSipId()) {
        if ("Boot" != strValue) {
            return InvalidParams;
        }
    } else if (NoneError == HasControlType(ReqMessage, "DragZoomIn", strValue) && DeviceId == m_ChannelItem.DeviceID) {
    } else if (NoneError == HasControlType(ReqMessage, "DragZoomOut", strValue) && DeviceId == m_ChannelItem.DeviceID) {
    } else if (NoneError == HasControlType(ReqMessage, "PTZPreciseCtrl", strValue) && DeviceId == m_ChannelItem.DeviceID) {
    } else if (NoneError == HasControlType(ReqMessage, "FormatSDCards", strValue) && DeviceId == GetSipId()) {
    } else if (NoneError == HasControlType(ReqMessage, "TargetTrack", strValue) && DeviceId == m_ChannelItem.DeviceID) {
    } else {
        if (NoneError == HasControlType(ReqMessage, "RecordCmd", strValue) && DeviceId == m_ChannelItem.DeviceID) {
            if ("Record" != strValue
                && "StopRecord" != strValue) {
                ErrorCode = InvalidParams;
            } else {
                m_bRecording = "Record" == strValue;
            }
        } else if (NoneError == HasControlType(ReqMessage, "GuardCmd", strValue) && DeviceId == m_AlarmItem.DeviceID) {
            if ("SetGuard" != strValue
                && "ResetGuard" != strValue) {
                ErrorCode = InvalidParams;
            } else {
                m_bAlarmSetGuard = "SetGuard" == strValue;
            }
        } else if (NoneError == HasControlType(ReqMessage, "AlarmCmd", strValue) && DeviceId == m_AlarmItem.DeviceID) {
            if ("ResetAlarm" != strValue) {
                ErrorCode = InvalidParams;
            } else {
                m_bAlarming = FALSE;
            }
        } else if (NoneError == HasControlType(ReqMessage, "HomePosition", strValue) && DeviceId == m_ChannelItem.DeviceID) {
            MkMap<MkString, struct _gb_message>::const_iterator itMap = ReqMessage.MapMessage.find("HomePosition");
            if (itMap != ReqMessage.MapMessage.end()) {
                m_HomePositonParam = itMap->second.MainParam;
            }
        } else if (NoneError == HasControlType(ReqMessage, "DeviceUpgrade", strValue) && DeviceId == GetSipId()) {
            MkMap<MkString, struct _gb_message>::const_iterator it = ReqMessage.MapMessage.find("DeviceUpgrade");
            if (it != ReqMessage.MapMessage.end()) {
                MkMapString::const_iterator itMap = it->second.MainParam.find("SessionID");
                if (itMap != it->second.MainParam.end()) {
                    m_UpdateSessionId = itMap->second;
                }
            }
            MkString UpgradeDelay;
            GetTimer()->AddDelayer([this]() {
                NotifyUpgradeSuccess();
            }, 5000, UpgradeDelay);

        } else {
            ErrorCode = InvalidParams;
        }
        if (InvalidParams != ErrorCode) {
            Res.m_Message.MainParam["Result"] = NoneError == ErrorCode ? "OK" : "ERROR";
        }
        *ppRes = &Res;
    }
    return ErrorCode;
}

Uint32 CMkSampleGbDevice::HasControlType(const MkGbMessage& ReqMessage, const MkString& ControlType, MkString& StrValue)
{
    MkMapString::const_iterator it = ReqMessage.MainParam.find(ControlType);
    if (it != ReqMessage.MainParam.end()) {
        StrValue = it->second;
        return NoneError;
    }
    MkMap<MkString, struct _gb_message>::const_iterator itMap = ReqMessage.MapMessage.find(ControlType);
    if (itMap != ReqMessage.MapMessage.end()) {
        return NoneError;
    }
    return InvalidParams;
}

Uint32 CMkSampleGbDevice::NotifyAlarm()
{
    if (!m_bAlarming || !m_bAlarmSetGuard) {
        return NoneError;
    }
    CMkGbMessageRequest Req;
    Req.m_DstId = m_ServerId;
    Req.m_DeviceId = m_AlarmItem.DeviceID;
    Req.m_RouterId = m_ServerId;
    Req.m_CmdType = "Alarm";
    Req.m_MessageType = "Notify";
    Req.m_Message.MainParam["AlarmPriority"] = "1";
    Req.m_Message.MainParam["AlarmMethod"] = "1";
    MkString StrTime;
    NowMkTime.GetString(StrTime);
    Req.m_Message.MainParam["AlarmTime"] = StrTime;
    Req.m_Message.MainParam["AlarmDescription"] = "123";
    Req.m_Message.MainParam["Longitude"] = "0.0";
    Req.m_Message.MainParam["Latitude"] = "0.0";
    Req.m_Message.InfoParam.push_back(MkPair<MkString, MkString>("AlarmType", "1"));
    Req.m_Message.InfoParam.push_back(MkPair<MkString, MkString>("AlarmTypeParam", "1"));
    MessageRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    return NoneError;
}

Uint32 CMkSampleGbDevice::NotifyUpgradeSuccess()
{
    CMkGbMessageRequest Req;
    Req.m_MessageType = "Notify";
    Req.m_CmdType = "DeviceUpgradeResult";
    Req.m_DstId = m_ServerId;
    Req.m_RouterId = m_ServerId;
    Req.m_DeviceId = GetSipId();
    Req.m_Message.MainParam["SessionId"] = m_UpdateSessionId;
    Req.m_Message.MainParam["UpgradeResult"] = "OK";
    Req.m_Message.MainParam["Firmeare"] = "11";
    MessageRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    return NoneError;
}

Uint32 CMkSampleGbDevice::NotifyMobilePosition()
{
    if (!m_bSubscribeMobilePosition) {
        return NoneError;
    }
    CMkGbNotifyRequest Req;
    Req.m_SubscribeId = m_SubscribeMobilePositionId;
    Req.m_DstId = m_ServerId;
    Req.m_DeviceId = GetSipId();
    Req.m_CmdType = "MobilePosition";
    Req.m_Expires = m_SubscribeMobilePositionExpires;
    Req.m_State = "active";
    Req.m_Event = m_SubscribeMobilePositionEvent;
    Req.m_MessageType = "Notify";
    Req.m_Message.MainParam["SumNum"] = "1";
    Req.m_Message.MainParam["Time"] = "2010-10-11T00:00:00";
    Req.m_Message.ChildKey = "DeviceList";
    Req.m_Message.ItemName = "Item";
    MkGbMessage ChildMsg;
    ChildMsg.MainParam["DeviceID"] = m_ChannelItem.DeviceID;
    ChildMsg.MainParam["CaptureTime"] = "2010-10-11T00:00:00";
    ChildMsg.MainParam["Longitude"] = "0.0";
    ChildMsg.MainParam["Latitude"] = "0.0";
    ChildMsg.MainParam["Speed"] = "1.0";
    ChildMsg.MainParam["Direction"] = "1.0";
    ChildMsg.MainParam["Altitude"] = "1.0";
    ChildMsg.MainParam["Height"] = "1.0";
    Req.m_Message.VecChildren.emplace_back(ChildMsg);
    NotifyRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    return NoneError;
}

Uint32 CMkSampleGbDevice::NotifyUploadSnapShotFinished()
{
    CMkGbMessageRequest Req;
    Req.m_MessageType = "Notify";
    Req.m_CmdType = "UploadSnapShotFilished";
    Req.m_DstId = m_ServerId;
    Req.m_RouterId = m_ServerId;
    Req.m_DeviceId = GetSipId();
    MkMapString::iterator it = m_SnapShot.MainParam.find("SessionID");
    if (it != m_SnapShot.MainParam.end()) {
        Req.m_Message.MainParam["SessionId"] = it->second;
    }
    Req.m_Message.SnapShotParam.push_back(MkPair<MkString, MkString>("SnapshotFileID", "111"));
    Req.m_Message.SnapShotParam.push_back(MkPair<MkString, MkString>("SnapshotFileID", "222"));
    MessageRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    return NoneError;
}

Uint32 CMkSampleGbDevice::NotifyCatalog()
{
    if (!m_bSubscribeCatalog) {
        return NoneError;
    }
    CMkGbNotifyRequest Req;
    Req.m_SubscribeId = m_SubscribeCatalogId;
    Req.m_MessageType = "Notify";
    Req.m_CmdType = "Catalog";
    Req.m_DstId = m_ServerId;
    Req.m_DeviceId = GetSipId();
    Req.m_Expires = m_SubscribeCatalogExpires;
    Req.m_State = "active";
    Req.m_Event = m_SubscribeCatalogEvent;
    Req.m_Message.MainParam["Status"] = "OK";
    Req.m_Message.MainParam["SumNum"] = "3";
    Req.m_Message.ChildKey = "DeviceList";
    Req.m_Message.ItemName = "Item";
    MkGbMessage ChildMsg;
    ChildMsg.MainParam["DeviceID"] = m_ChannelItem.DeviceID;
    ChildMsg.MainParam["Event"] = "ON";
    Req.m_Message.VecChildren.emplace_back(ChildMsg);
    ChildMsg.MainParam["DeviceID"] = m_AlarmItem.DeviceID;
    ChildMsg.MainParam["Event"] = "ON";
    Req.m_Message.VecChildren.emplace_back(ChildMsg);
    ChildMsg.MainParam["DeviceID"] = m_AudioOutItem.DeviceID;
    ChildMsg.MainParam["Event"] = "ON";
    Req.m_Message.VecChildren.emplace_back(ChildMsg);
    NotifyRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    return NoneError;
}

Uint32 CMkSampleGbDevice::NotifyPtzPosition()
{
    if (!m_bSubscribePtzPosition) {
        return NoneError;
    }
    CMkGbNotifyRequest Req;
    Req.m_SubscribeId = m_SubscribePtzPositionId;
    Req.m_MessageType = "Notify";
    Req.m_CmdType = "PTZPosition";
    Req.m_DstId = m_ServerId;
    Req.m_DeviceId = m_ChannelItem.DeviceID;
    Req.m_Expires = m_SubscribePtzPositionExpires;
    Req.m_State = "active";
    Req.m_Event = m_SubscribePtzPositionEvent;
    Req.m_Message.MainParam["Pan"] = "1.0";
    Req.m_Message.MainParam["Tilt"] = "1.0";
    Req.m_Message.MainParam["Zoom"] = "1.0";
    Req.m_Message.MainParam["HorizontalFieldAngle"] = "1.0";
    Req.m_Message.MainParam["VerticalFieldAngle"] = "1.0";
    Req.m_Message.MainParam["MaxViewDistance"] = "10.0";
    NotifyRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    return NoneError;
}

Uint32 CMkSampleGbDevice::StartGetAudio(const MkString& SourceId)
{
    return NoneError;
}

Uint32 CMkSampleGbDevice::VideoUploadNotify()
{
    CMkGbMessageRequest Req;
    Req.m_MessageType = "Notify";
    Req.m_CmdType = "DeviceUpgradeResult";
    Req.m_DstId = m_ServerId;
    Req.m_DeviceId = m_ChannelItem.DeviceID;
    Req.m_RouterId = m_ServerId;
    Req.m_Message.MainParam["Time"] = "2010-10-11T00:00:00";
    Req.m_Message.MainParam["Longitude"] = "0.0";
    Req.m_Message.MainParam["Latitude"] = "1.1";
    MessageRequest(Req, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    return NoneError;
}

Uint32 CMkSampleGbDevice::MediaStatusNotify()
{
    CMkGbMessageRequest Req;
    Req.m_MessageType = "Notify";
    Req.m_CmdType = "MediaStatus";
    Req.m_DstId = m_ServerId;
    Req.m_DeviceId = m_ChannelItem.DeviceID;
    Req.m_RouterId = m_ServerId;
    Req.m_Message.MainParam["NotifyType"] = "121";
    //InviteMessageRequest(Req, m_RealPlaySessionId, [this](Uint32 ErrorCode, const CMkGbResponse* pGbRes) {});
    return NoneError;
}

CMkSampleGbDevice::~CMkSampleGbDevice()
{

}